home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / quake.zip / BOMBS.ZIP / WEAPONS.QC < prev   
Text File  |  1997-02-09  |  45KB  |  1,964 lines

  1. /*
  2.  
  3. Bouncing Fragmentation Grenade!    7/28/96 by Steve Bond
  4. Email: wedge@nuc.net    WWW: http://www.nuc.net/quake
  5.  
  6. >>>READ THE README!
  7.  
  8. Hey ID! 
  9. If you are reading this, PUH-LEEZE fly me and John to Texas!
  10. We'll scrub the shitters at id for the chance to shake hands!
  11. (I mean - we'll wash our hands first and everything)
  12.  
  13. */
  14.  
  15. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  16. void () player_run;
  17. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  18. void(vector org, vector vel, float damage) SpawnBlood;
  19. void() SuperDamageSound;
  20.  
  21. float bombtimer;
  22.  
  23.  
  24. void() W_FireBomb;
  25. void() BombTouch;
  26. void() BombExplode;
  27. void() BombExplosion;
  28. void() ShrapnelExplode;
  29. void() BombTime;
  30. void() W_FireGIBGUN;
  31. void() T_GIBTouch;
  32. void() GIBExplode;
  33. void() W_FireFLASH;
  34. void() T_FlashTouch;
  35. void() SelfDestruct;
  36.  
  37. // called by worldspawn
  38. void() W_Precache =
  39. {
  40.     precache_sound ("weapons/r_exp3.wav");  // new rocket explosion
  41.     precache_sound ("weapons/rocket1i.wav");        // spike gun
  42.     precache_sound ("weapons/sgun1.wav");
  43.     precache_sound ("weapons/guncock.wav"); // player shotgun
  44.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  45.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  46.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  47.     precache_sound ("weapons/spike2.wav");  // super spikes
  48.     precache_sound ("weapons/tink1.wav");   // spikes tink (used in c code)
  49.     precache_sound ("weapons/grenade.wav"); // grenade launcher
  50.     precache_sound ("weapons/bounce.wav");          // grenade bounce
  51.     precache_sound ("weapons/shotgn2.wav"); // super shotgun
  52.     precache_sound ("items/damage2.wav");
  53.     precache_sound ("player/tornoff2.wav");
  54.     precache_sound ("player/lburn1.wav");
  55.     precache_sound ("doors/airdoor2.wav");
  56.  
  57.  
  58. };
  59.  
  60. float() crandom =
  61. {
  62.     return 2*(random() - 0.5);
  63. };
  64.  
  65. /*
  66. ================
  67. W_FireAxe
  68. ================
  69. */
  70. void() W_FireAxe =
  71. {
  72.     local   vector  source;
  73.     local   vector  org;
  74.  
  75.     source = self.origin + '0 0 16';
  76.     traceline (source, source + v_forward*64, FALSE, self);
  77.     if (trace_fraction == 1.0)
  78.         return;
  79.     
  80.     org = trace_endpos - v_forward*4;
  81.  
  82.     if (trace_ent.takedamage)
  83.     {
  84.         trace_ent.axhitme = 1;
  85.         SpawnBlood (org, '0 0 0', 20);
  86.         T_Damage (trace_ent, self, self, 20);
  87.     }
  88.     else
  89.     {       // hit wall
  90.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  91.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  92.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  93.         WriteCoord (MSG_BROADCAST, org_x);
  94.         WriteCoord (MSG_BROADCAST, org_y);
  95.         WriteCoord (MSG_BROADCAST, org_z);
  96.     }
  97. };
  98.  
  99.  
  100. //============================================================================
  101.  
  102.  
  103. vector() wall_velocity =
  104. {
  105.     local vector    vel;
  106.     
  107.     vel = normalize (self.velocity);
  108.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  109.     vel = vel + 2*trace_plane_normal;
  110.     vel = vel * 200;
  111.     
  112.     return vel;
  113. };
  114.  
  115.  
  116. /*
  117. ================
  118. SpawnMeatSpray
  119. ================
  120. */
  121. void(vector org, vector vel) SpawnMeatSpray =
  122. {
  123.     local   entity missile, mpuff;
  124.     local   vector  org;
  125.  
  126.     missile = spawn ();
  127.     missile.owner = self;
  128.     missile.movetype = MOVETYPE_BOUNCE;
  129.     missile.solid = SOLID_NOT;
  130.  
  131.     makevectors (self.angles);
  132.  
  133.     missile.velocity = vel;
  134.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  135.  
  136.     missile.avelocity = '3000 1000 2000';
  137.     
  138. // set missile duration
  139.     missile.nextthink = time + 1;
  140.     missile.think = SUB_Remove;
  141.  
  142.     setmodel (missile, "progs/zom_gib.mdl");
  143.     setsize (missile, '0 0 0', '0 0 0');            
  144.     setorigin (missile, org);
  145. };
  146.  
  147. /*
  148. ================
  149. SpawnBlood
  150. ================
  151. */
  152. void(vector org, vector vel, float damage) SpawnBlood =
  153. {
  154.     particle (org, vel*0.1, 73, damage*2);
  155. };
  156.  
  157. /*
  158. ================
  159. spawn_touchblood
  160. ================
  161. */
  162. void(float damage) spawn_touchblood =
  163. {
  164.     local vector    vel;
  165.  
  166.     vel = wall_velocity () * 0.2;
  167.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  168. };
  169.  
  170.  
  171. /*
  172. ================
  173. SpawnChunk
  174. ================
  175. */
  176. void(vector org, vector vel) SpawnChunk =
  177. {
  178.     particle (org, vel*0.02, 0, 10);
  179. };
  180.  
  181. /*
  182. ==============================================================================
  183.  
  184. MULTI-DAMAGE
  185.  
  186. Collects multiple small damages into a single damage
  187.  
  188. ==============================================================================
  189. */
  190.  
  191. entity  multi_ent;
  192. float   multi_damage;
  193.  
  194. void() ClearMultiDamage =
  195. {
  196.     multi_ent = world;
  197.     multi_damage = 0;
  198. };
  199.  
  200. void() ApplyMultiDamage =
  201. {
  202.     if (!multi_ent)
  203.         return;
  204.     T_Damage (multi_ent, self, self, multi_damage);
  205. };
  206.  
  207. void(entity hit, float damage) AddMultiDamage =
  208. {
  209.     if (!hit)
  210.         return;
  211.     
  212.     if (hit != multi_ent)
  213.     {
  214.         ApplyMultiDamage ();
  215.         multi_damage = damage;
  216.         multi_ent = hit;
  217.     }
  218.     else
  219.         multi_damage = multi_damage + damage;
  220. };
  221.  
  222. /*
  223. ==============================================================================
  224.  
  225. BULLETS
  226.  
  227. ==============================================================================
  228. */
  229.  
  230. /*
  231. ================
  232. TraceAttack
  233. ================
  234. */
  235. void(float damage, vector dir) TraceAttack =
  236. {
  237.     local   vector  vel, org;
  238.     
  239.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  240.     vel = vel + 2*trace_plane_normal;
  241.     vel = vel * 200;
  242.  
  243.     org = trace_endpos - dir*4;
  244.  
  245.     if (trace_ent.takedamage)
  246.     {
  247.         SpawnBlood (org, vel*0.2, damage);
  248.         AddMultiDamage (trace_ent, damage);
  249.     }
  250.     else
  251.     {
  252.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  253.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  254.         WriteCoord (MSG_BROADCAST, org_x);
  255.         WriteCoord (MSG_BROADCAST, org_y);
  256.         WriteCoord (MSG_BROADCAST, org_z);
  257.     }
  258. };
  259.  
  260. /*
  261. ================
  262. FireBullets
  263.  
  264. Used by shotgun, super shotgun, and enemy soldier firing
  265. Go to the trouble of combining multiple pellets into a single damage call.
  266. ================
  267. */
  268. void(float shotcount, vector dir, vector spread) FireBullets =
  269. {
  270.     local   vector direction;
  271.     local   vector  src;
  272.     
  273.     makevectors(self.v_angle);
  274.  
  275.     src = self.origin + v_forward*10;
  276.     src_z = self.absmin_z + self.size_z * 0.7;
  277.  
  278.     ClearMultiDamage ();
  279.     while (shotcount > 0)
  280.     {
  281.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  282.  
  283.         traceline (src, src + direction*2048, FALSE, self);
  284.         if (trace_fraction != 1.0)
  285.             TraceAttack (4, direction);
  286.  
  287.         shotcount = shotcount - 1;
  288.     }
  289.     ApplyMultiDamage ();
  290. };
  291.  
  292. /*
  293. ================
  294. W_FireShotgun
  295. ================
  296. */
  297. void() W_FireShotgun =
  298. {
  299.     local vector dir;
  300.  
  301.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); 
  302.  
  303.     self.punchangle_x = -2;
  304.     
  305.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  306.     dir = aim (self, 100000);
  307.     FireBullets (6, dir, '0.04 0.04 0');
  308. };
  309.  
  310.  
  311. /*
  312. ================
  313. W_FireSuperShotgun
  314. ================
  315. */
  316. void() W_FireSuperShotgun =
  317. {
  318.     local vector dir;
  319.  
  320.     if (self.currentammo == 1)
  321.     {
  322.         W_FireShotgun ();
  323.         return;
  324.     }
  325.         
  326.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); 
  327.  
  328.     self.punchangle_x = -4;
  329.     
  330.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  331.     dir = aim (self, 100000);
  332.     FireBullets (14, dir, '0.14 0.08 0');
  333. };
  334.  
  335.  
  336. /*
  337. ==============================================================================
  338.  
  339. ROCKETS
  340.  
  341. ==============================================================================
  342. */
  343.  
  344. void()  s_explode1      =       [0,             s_explode2] {};
  345. void()  s_explode2      =       [1,             s_explode3] {};
  346. void()  s_explode3      =       [2,             s_explode4] {};
  347. void()  s_explode4      =       [3,             s_explode5] {};
  348. void()  s_explode5      =       [4,             s_explode6] {};
  349. void()  s_explode6      =       [5,             SUB_Remove] {};
  350.  
  351. void() BecomeExplosion =
  352. {
  353.     self.movetype = MOVETYPE_NONE;
  354.     self.velocity = '0 0 0';
  355.     self.touch = SUB_Null;
  356.     setmodel (self, "progs/s_explod.spr");
  357.     self.solid = SOLID_NOT;
  358.     s_explode1 ();
  359. };
  360.  
  361. void() T_MissileTouch =
  362. {
  363.     local float     damg;
  364.  
  365.     if (other == self.owner)
  366.         return;         // don't explode on owner
  367.  
  368.     if (pointcontents(self.origin) == CONTENT_SKY)
  369.     {
  370.         remove(self);
  371.         return;
  372.     }
  373.  
  374.     damg = 100 + random()*20;
  375.     
  376.     if (other.health)
  377.     {
  378.         if (other.classname == "monster_shambler")
  379.             damg = damg * 0.5;      // mostly immune
  380.         T_Damage (other, self, self.owner, damg );
  381.     }
  382.  
  383.     // don't do radius damage to the other, because all the damage
  384.     // was done in the impact
  385.     T_RadiusDamage (self, self.owner, 120, other);
  386.  
  387. //      sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  388.     self.origin = self.origin - 8*normalize(self.velocity);
  389.  
  390.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  391.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  392.     WriteCoord (MSG_BROADCAST, self.origin_x);
  393.     WriteCoord (MSG_BROADCAST, self.origin_y);
  394.     WriteCoord (MSG_BROADCAST, self.origin_z);
  395.  
  396.     BecomeExplosion ();
  397. };
  398.  
  399.  
  400.  
  401. /*
  402. ================
  403. W_FireRocket
  404. ================
  405. */
  406. void() W_FireRocket =
  407. {
  408.     local   entity missile, mpuff;
  409.     
  410.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  411.     
  412.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  413.  
  414.     self.punchangle_x = -2;
  415.  
  416.     missile = spawn ();
  417.     missile.owner = self;
  418.     missile.movetype = MOVETYPE_FLYMISSILE;
  419.     missile.solid = SOLID_BBOX;
  420.     missile.classname = "Rocket";
  421.     
  422. // set missile speed    
  423.  
  424.     makevectors (self.v_angle);
  425.     missile.velocity = aim(self, 1000);
  426.     missile.velocity = missile.velocity * 1000;
  427.     missile.angles = vectoangles(missile.velocity);
  428.     
  429.     missile.touch = T_MissileTouch;
  430.     
  431. // set missile duration
  432.     missile.nextthink = time + 5;
  433.     missile.think = SUB_Remove;
  434.  
  435.     setmodel (missile, "progs/missile.mdl");
  436.     setsize (missile, '0 0 0', '0 0 0');            
  437.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  438. };
  439.  
  440. /*
  441. ===============================================================================
  442.  
  443. LIGHTNING
  444.  
  445. ===============================================================================
  446. */
  447.  
  448. /*
  449. =================
  450. LightningDamage
  451. =================
  452. */
  453. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  454. {
  455.     local entity            e1, e2;
  456.     local vector            f;
  457.     
  458.     f = p2 - p1;
  459.     normalize (f);
  460.     f_x = 0 - f_y;
  461.     f_y = f_x;
  462.     f_z = 0;
  463.     f = f*16;
  464.  
  465.     e1 = e2 = world;
  466.  
  467.     traceline (p1, p2, FALSE, self);
  468.     if (trace_ent.takedamage)
  469.     {
  470.         particle (trace_endpos, '0 0 100', 225, damage*4);
  471.         T_Damage (trace_ent, from, from, damage);
  472.         if (self.classname == "player")
  473.         {
  474.             if (other.classname == "player")
  475.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  476.         }
  477.     }
  478.     e1 = trace_ent;
  479.  
  480.     traceline (p1 + f, p2 + f, FALSE, self);
  481.     if (trace_ent != e1 && trace_ent.takedamage)
  482.     {
  483.         particle (trace_endpos, '0 0 100', 225, damage*4);
  484.         T_Damage (trace_ent, from, from, damage);
  485.     }
  486.     e2 = trace_ent;
  487.  
  488.     traceline (p1 - f, p2 - f, FALSE, self);
  489.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  490.     {
  491.         particle (trace_endpos, '0 0 100', 225, damage*4);
  492.         T_Damage (trace_ent, from, from, damage);
  493.     }
  494. };
  495.  
  496.  
  497. void() W_FireLightning =
  498. {
  499.     local   vector          org;
  500.  
  501.     if (self.ammo_cells < 1)
  502.     {
  503.         self.weapon = W_BestWeapon ();
  504.         W_SetCurrentAmmo ();
  505.         return;
  506.     }
  507.  
  508. // explode if under water
  509.     if (self.waterlevel > 1)
  510.     {
  511.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  512.         self.ammo_cells = 0;
  513.         W_SetCurrentAmmo ();
  514.         return;
  515.     }
  516.  
  517.     if (self.t_width < time)
  518.     {
  519.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  520.         self.t_width = time + 0.6;
  521.     }
  522.     self.punchangle_x = -2;
  523.  
  524.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  525.  
  526.     org = self.origin + '0 0 16';
  527.     
  528.     traceline (org, org + v_forward*600, TRUE, self);
  529.  
  530.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  531.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  532.     WriteEntity (MSG_BROADCAST, self);
  533.     WriteCoord (MSG_BROADCAST, org_x);
  534.     WriteCoord (MSG_BROADCAST, org_y);
  535.     WriteCoord (MSG_BROADCAST, org_z);
  536.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  537.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  538.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  539.  
  540.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  541. };
  542.  
  543.  
  544. //=============================================================================
  545.  
  546.  
  547. void() GrenadeExplode =
  548. {
  549.     T_RadiusDamage (self, self.owner, 120, world);
  550.  
  551.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  552.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  553.     WriteCoord (MSG_BROADCAST, self.origin_x);
  554.     WriteCoord (MSG_BROADCAST, self.origin_y);
  555.     WriteCoord (MSG_BROADCAST, self.origin_z);
  556.  
  557.     BecomeExplosion ();
  558. };
  559.  
  560. void() GrenadeTouch =
  561. {
  562.     if (other == self.owner)
  563.         return;         // don't explode on owner
  564.     if (other.takedamage == DAMAGE_AIM)
  565.     {
  566.         GrenadeExplode();
  567.         return;
  568.     }
  569.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  570.     if (self.velocity == '0 0 0')
  571.         self.avelocity = '0 0 0';
  572. };
  573.  
  574. /*
  575. ================
  576. W_FireGrenade
  577. ================
  578. */
  579. void() W_FireGrenade =
  580. {
  581.     local   entity missile, mpuff;
  582.     
  583.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  584.     
  585.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  586.  
  587.     self.punchangle_x = -2;
  588.  
  589.     missile = spawn ();
  590.     missile.owner = self;
  591.     missile.movetype = MOVETYPE_BOUNCE;
  592.     missile.solid = SOLID_BBOX;
  593.     missile.classname = "grenade";
  594.         
  595. // set missile speed    
  596.  
  597.     makevectors (self.v_angle);
  598.  
  599.     if (self.v_angle_x)
  600.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  601.     else
  602.     {
  603.         missile.velocity = aim(self, 10000);
  604.         missile.velocity = missile.velocity * 600;
  605.         missile.velocity_z = 200;
  606.     }
  607.  
  608.     missile.avelocity = '300 300 300';
  609.  
  610.     missile.angles = vectoangles(missile.velocity);
  611.     
  612.     missile.touch = GrenadeTouch;
  613.     
  614. // set missile duration
  615.     missile.nextthink = time + 2.5;
  616.     missile.think = GrenadeExplode;
  617.  
  618.     setmodel (missile, "progs/grenade.mdl");
  619.     setsize (missile, '0 0 0', '0 0 0');            
  620.     setorigin (missile, self.origin);
  621. };
  622.  
  623.  
  624. //=============================================================================
  625.  
  626. void() spike_touch;
  627. void() superspike_touch;
  628.  
  629.  
  630. /*
  631. ===============
  632. launch_spike
  633.  
  634. Used for both the player and the ogre
  635. ===============
  636. */
  637. void(vector org, vector dir) launch_spike =
  638. {
  639.     newmis = spawn ();
  640.     newmis.owner = self;
  641.     newmis.movetype = MOVETYPE_FLYMISSILE;
  642.     newmis.solid = SOLID_BBOX;
  643.  
  644.     newmis.angles = vectoangles(dir);
  645.     
  646.     newmis.touch = spike_touch;
  647.     newmis.classname = "spike";
  648.     newmis.think = SUB_Remove;
  649. // Bump the nail's lifespan up to 11 seconds(?),so it will stick for a bit        
  650.     newmis.nextthink = time + 11;
  651.     setmodel (newmis, "progs/spike.mdl");
  652.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  653.     setorigin (newmis, org);
  654.  
  655.     newmis.velocity = dir * 1000;
  656. };
  657.  
  658. void() W_FireSuperSpikes =
  659. {
  660.     local vector    dir;
  661.     local entity    old;
  662.     
  663.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  664.     self.attack_finished = time + 0.2;
  665.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  666.     dir = aim (self, 1000);
  667.     launch_spike (self.origin + '0 0 16', dir);
  668.     newmis.touch = superspike_touch;
  669.     setmodel (newmis, "progs/s_spike.mdl");
  670.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  671.     self.punchangle_x = -2;
  672. };
  673.  
  674. void(float ox) W_FireSpikes =
  675. {
  676.     local vector    dir;
  677.     local entity    old;
  678.     
  679.     makevectors (self.v_angle);
  680.     
  681.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  682.     {
  683.         W_FireSuperSpikes ();
  684.         return;
  685.     }
  686.  
  687.     if (self.ammo_nails < 1)
  688.     {
  689.         self.weapon = W_BestWeapon ();
  690.         W_SetCurrentAmmo ();
  691.         return;
  692.     }
  693.  
  694.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  695.     self.attack_finished = time + 0.2;
  696.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  697.     dir = aim (self, 1000);
  698.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  699.  
  700.     self.punchangle_x = -2;
  701. };
  702.  
  703.  
  704.  
  705. .float hit_z;
  706. void() spike_touch =
  707. {
  708. local float rand;
  709.     if (other == self.owner)
  710.         return;
  711.  
  712.     if (other.solid == SOLID_TRIGGER)
  713.         return; // trigger field, do nothing
  714.  
  715.     if (pointcontents(self.origin) == CONTENT_SKY)
  716.     {
  717.         remove(self);
  718.         return;
  719.     }
  720.     
  721. // hit something that bleeds
  722.     if (other.takedamage)
  723.     {
  724.         spawn_touchblood (9);
  725.         T_Damage (other, self, self.owner, 9);
  726.         remove(self);
  727.     }
  728.     else
  729.     {
  730.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  731.         
  732.         if (self.classname == "wizspike")
  733.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  734.         else if (self.classname == "knightspike")
  735.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  736.         else
  737.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  738.         WriteCoord (MSG_BROADCAST, self.origin_x);
  739.         WriteCoord (MSG_BROADCAST, self.origin_y);
  740.         WriteCoord (MSG_BROADCAST, self.origin_z);
  741.     }
  742.  
  743. /*
  744. DO NOT let the nail remove itself. This section of code is only executed
  745. when the nail has hit a wall, floor, or plat. These are places we want the 
  746. nail to stick, so we comment out the REMOVE(SELF); function call
  747. */
  748.     self.velocity='0 0 0'; // make the nail stop!
  749.     remove(self);
  750.  
  751. };
  752.  
  753. void() superspike_touch =
  754. {
  755. local float rand;
  756.     if (other == self.owner)
  757.         return;
  758.  
  759.     if (other.solid == SOLID_TRIGGER)
  760.         return; // trigger field, do nothing
  761.  
  762.     if (pointcontents(self.origin) == CONTENT_SKY)
  763.     {
  764.         remove(self);
  765.         return;
  766.     }
  767.     
  768. // hit something that bleeds
  769.     if (other.takedamage)
  770.     {
  771.         spawn_touchblood (18);
  772.         T_Damage (other, self, self.owner, 18);
  773.     }
  774.     else
  775.     {
  776.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  777.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  778.         WriteCoord (MSG_BROADCAST, self.origin_x);
  779.         WriteCoord (MSG_BROADCAST, self.origin_y);
  780.         WriteCoord (MSG_BROADCAST, self.origin_z);
  781.     }
  782.  
  783.     remove(self);
  784.  
  785. };
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792. /*========================================================================
  793. BOUNCING FRAGMENTATION GRENADE - Version .9
  794. 7/28/96 - Steve Bond  email:wedge@nuc.net
  795. http://www.nuc.net/quake
  796. =======================================================================*/
  797.  
  798. //This code segment handles the impact of shrapnel
  799. //this is merely id's superspike_touch code, reworked
  800. void() shrapnel_touch =
  801. {
  802. local float rand;
  803. // has the shrapnel hit a switch? 
  804.     if (other.solid == SOLID_TRIGGER)
  805.         return; // trigger field, do nothing
  806.  
  807. // has the shrapnel hit the sky?
  808.     if (pointcontents(self.origin) == CONTENT_SKY)
  809.     {
  810.         remove(self);
  811.         return;
  812.     }
  813.     
  814. // has the shrapnel hit a living thing?
  815.     if (other.takedamage)
  816.     {
  817.         spawn_touchblood (18);
  818.         T_Damage (other, self, self.owner, 18);
  819.     }
  820.     else
  821.     {
  822.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  823.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  824.         WriteCoord (MSG_BROADCAST, self.origin_x);
  825.         WriteCoord (MSG_BROADCAST, self.origin_y);
  826.         WriteCoord (MSG_BROADCAST, self.origin_z);
  827.     }
  828.  
  829. };
  830.  
  831. /*
  832. Code to spawn ONE randomly directed piece of shrapnel
  833. this is id's launch_spike code, reworked
  834. Pass a vector to this function to determine the shrap's origin
  835. */
  836. void (vector org, float spin, entity shooter) launch_shrapnel=
  837. {
  838.     local float xdir,ydir,zdir;
  839.     
  840. //Assign a random direction for the shrapnel to fly in
  841.     xdir = 110 * random() - 55;
  842.     ydir = 110 * random() - 55;
  843.     zdir = 50 * random() - 25;
  844.  
  845.     newmis = spawn ();
  846.     newmis.owner = shooter;
  847.     newmis.movetype = MOVETYPE_BOUNCE;
  848.     self.touch = SUB_Null;
  849.     newmis.solid = SOLID_BBOX;
  850.  
  851.     newmis.touch = shrapnel_touch;
  852.     newmis.classname = "spike";
  853.     newmis.think =     ShrapnelExplode;
  854.     
  855. // this is how many seconds(?) the nails can exist.        
  856.     newmis.nextthink = time + 0.75;
  857.     
  858. // speed at which to move the shrapnel        
  859.     newmis.velocity_x = xdir * 5;
  860.     newmis.velocity_y = ydir * 5;
  861.     newmis.velocity_z = zdir * 10;
  862.  
  863. /*
  864. as best I can figure, AVELOCITY means "attitude velocity"        
  865. or something thereabouts. Anyway, it makes shit spin on 
  866. the x,y,z axes by the given velocity for each axis. In this 
  867. case, it makes the shrapnel spin in flight. Good stuff.
  868. this segment assigns one of five preset attitudes for 
  869. each piece of shrapnel, based on the number passed to the
  870. function.
  871. */        
  872.     if (spin == 0)
  873.     newmis.avelocity='250 300 400';
  874.     if (spin == 1)
  875.     newmis.avelocity='400 250 300';
  876.     if (spin == 2)
  877.     newmis.avelocity='300 400 250';
  878.     if (spin == 3)
  879.     newmis.avelocity='300 300 300';
  880.     if (spin == 4) 
  881.     newmis.avelocity='400 250 400';
  882.  
  883.     setmodel (newmis, "progs/grenade.mdl");
  884.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
  885.     setorigin (newmis, org);
  886. };
  887.  
  888. // This code segment detonates the 'second stage' of the grenade
  889. // (After it has popped up)
  890. void()  BouncerExplode =
  891. {
  892.     
  893. // Do the damage
  894.     T_RadiusDamage (self, self.owner, 120, world);
  895. // Tell the network
  896.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  897.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  898.     WriteCoord (MSG_BROADCAST, self.origin_x);
  899.     WriteCoord (MSG_BROADCAST, self.origin_y);
  900.     WriteCoord (MSG_BROADCAST, self.origin_z);
  901.  
  902. // Let Quake handle the explosion and deallocation of the grenade        
  903.     self.solid=SOLID_NOT;
  904.     BecomeExplosion ();
  905.  
  906. // Launch a hail (20 pieces) of shrapnel
  907.     launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
  908.     launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
  909.     launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
  910.     launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
  911.     launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
  912.     launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
  913.     launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
  914.     launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
  915.     launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
  916.     launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
  917.     
  918. };
  919.  
  920. /*
  921. This code segment makes the 'first stage' of the bouncer pop upward
  922. after it's time has expired.
  923. */
  924. void() BouncerTouch;
  925. void() BouncerPopUp=
  926. {
  927.     local entity missile, mpuff;
  928.  
  929. // Make the grenade stop
  930.     self.movetype=MOVETYPE_NONE;
  931.     self.velocity='0 0 0';
  932. // Draw a tiny explosion (no particles)        
  933.     setmodel (self, "progs/s_explod.spr");
  934.     s_explode1 ();
  935. // Make the :FOOMP: grenade launcher sound        
  936.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  937. // Spawn and animate the 'second stage'
  938.     missile = spawn ();
  939.     missile.owner = self.owner;
  940.     missile.movetype = MOVETYPE_BOUNCE;
  941.     missile.solid = SOLID_BBOX;
  942.     missile.classname = "grenade";
  943. // Set speed
  944.     missile.velocity = '0 0 650';
  945.     missile.angles = vectoangles(missile.velocity);
  946.     missile.touch = BouncerTouch;
  947. // Set Duration
  948.     missile.nextthink = time + 1;
  949.     missile.think = BouncerExplode;
  950.  
  951.     setmodel (missile, "progs/missile.mdl");
  952.     setsize (missile, '0 0 0', '0 0 0');
  953.     setorigin (missile, self.origin);
  954. };
  955.  
  956. // This code segment handles collisions for the 'first stage'
  957. // Of the grenade (after launch and before popup)
  958.  
  959. void() BouncerTouch =
  960. {
  961. //Did the grenade hit a 'living' thing?
  962.     if (other.takedamage)
  963.     {
  964. // yes, so play the bounce sound
  965.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  966. // now, exit the function without cause damage to the thing        
  967.     return;
  968.     }
  969.  
  970. // This controls what happens when the grenade hits walls, etz        
  971. // It just plays the sound and bounces on
  972.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  973.     if (self.velocity == '0 0 0')
  974.         self.avelocity = '0 0 0';
  975. };
  976.  
  977. /*
  978. This code segment handles the launching of the Bouncing Fragmentation Grenade
  979. this is a reworked copy of id's W_launchgrenade code
  980. */
  981. void() W_LaunchBouncer =
  982. {
  983. // If player doesn't have 3 or more rockets, don't launch
  984.     if ((self.ammo_rockets < 5) || !(self.weapon & (IT_GRENADE_LAUNCHER | IT_FIREWALL | IT_BOMB)))
  985.     {
  986.     return;
  987.     }
  988.  
  989.     local   entity missile, mpuff;
  990.     
  991. // Take 3 rockets from the player        
  992.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  993.     
  994.     //sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  995. /*
  996. self.punchangle_x (x, y, or z) defines how hard the weapon         
  997. recoils (or 'punches' the player, making the screen shake)
  998. */        
  999.     self.punchangle_x = -2;
  1000.  
  1001. // This spawns the grenade - it is all id's standard grenade code        
  1002.     missile = spawn ();
  1003.     missile.owner = self;
  1004.     missile.movetype = MOVETYPE_BOUNCE;
  1005.     missile.solid = SOLID_BBOX;
  1006.     missile.classname = "grenade";
  1007.         
  1008. // set missile speed    
  1009.  
  1010.     makevectors (self.v_angle);
  1011.  
  1012.     if (self.v_angle_x)
  1013.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1014.     else
  1015.     {
  1016.         missile.velocity = aim(self, 10000);
  1017.         missile.velocity = missile.velocity * 600;
  1018.         missile.velocity_z = 200;
  1019.     }
  1020.  
  1021.     missile.avelocity = '300 300 300';
  1022.  
  1023.     missile.angles = vectoangles(missile.velocity);
  1024.     
  1025. // if the grenade touches anything, BouncerTouch() is called        
  1026.     missile.touch = BouncerTouch;
  1027.     
  1028. // Grenade has a maximum lifespan of 1.5 (seconds?)
  1029. // set missile duration
  1030.     missile.nextthink = time + 1;
  1031.     
  1032. // when the grenade's lifespan has expired, BouncerPopUp() is called        
  1033.     missile.think = BouncerPopUp;
  1034.  
  1035.     setmodel (missile, "progs/grenade.mdl");
  1036.     setsize (missile, '0 0 0', '0 0 0');            
  1037.     setorigin (missile, self.origin);
  1038. //    sprint(self,"Gib 'em!\n");
  1039. };
  1040. /*
  1041. ===============================================================================
  1042. End of Bouncing Fragmentation Grenade code.
  1043. ===============================================================================
  1044. */
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051. /*
  1052.  
  1053. PLAYER WEAPON USE
  1054.  
  1055. ===============================================================================
  1056. */
  1057.  
  1058. void() W_SetCurrentAmmo =
  1059. {
  1060.     player_run ();          // get out of any weapon firing states
  1061.  
  1062.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1063.     
  1064.     if (self.weapon == IT_AXE)
  1065.     {
  1066.         self.currentammo = 0;
  1067.         self.weaponmodel = "progs/v_axe.mdl";
  1068.         self.weaponframe = 0;
  1069.     }
  1070.     else if (self.weapon == IT_SHOTGUN)
  1071.     {
  1072.         self.currentammo = self.ammo_shells;
  1073.         self.weaponmodel = "progs/v_shot.mdl";
  1074.         self.weaponframe = 0;
  1075.         self.items = self.items | IT_SHELLS;
  1076.     }
  1077.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1078.     {
  1079.         self.currentammo = self.ammo_shells;
  1080.         self.weaponmodel = "progs/v_shot2.mdl";
  1081.         self.weaponframe = 0;
  1082.         self.items = self.items | IT_SHELLS;
  1083.     }
  1084.     else if (self.weapon == IT_NAILGUN)
  1085.     {
  1086.         self.currentammo = self.ammo_nails;
  1087.         self.weaponmodel = "progs/v_nail.mdl";
  1088.         self.weaponframe = 0;
  1089.         self.items = self.items | IT_NAILS;
  1090.     }
  1091.     else if (self.weapon == IT_SUPER_NAILGUN)
  1092.     {
  1093.         self.currentammo = self.ammo_nails;
  1094.         self.weaponmodel = "progs/v_nail2.mdl";
  1095.         self.weaponframe = 0;
  1096.         self.items = self.items | IT_NAILS;
  1097.     }
  1098.     else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
  1099.     {
  1100.         self.currentammo = self.ammo_rockets;
  1101.         self.weaponmodel = "progs/v_rock.mdl";
  1102.         self.weaponframe = 0;
  1103.         self.items = self.items | IT_ROCKETS;
  1104.     }
  1105.     else if (self.weapon == IT_ROCKET_LAUNCHER || (self.weapon == IT_GIBGUN) || (self.weapon == IT_FLASH))
  1106.     {
  1107.         self.currentammo = self.ammo_rockets;
  1108.         self.weaponmodel = "progs/v_rock2.mdl";
  1109.         self.weaponframe = 0;
  1110.         self.items = self.items | IT_ROCKETS;
  1111.     }
  1112.     else if (self.weapon == IT_LIGHTNING)
  1113.     {
  1114.         self.currentammo = self.ammo_cells;
  1115.         self.weaponmodel = "progs/v_light.mdl";
  1116.         self.weaponframe = 0;
  1117.         self.items = self.items | IT_CELLS;
  1118.     }
  1119.     else
  1120.     {
  1121.         self.currentammo = 0;
  1122.         self.weaponmodel = "";
  1123.         self.weaponframe = 0;
  1124.     }
  1125. };
  1126.  
  1127. float() W_BestWeapon =
  1128. {
  1129.     local   float   it;
  1130.     
  1131.     it = self.items;
  1132.  
  1133.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1134.         return IT_LIGHTNING;
  1135.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1136.         return IT_SUPER_NAILGUN;
  1137.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1138.         return IT_SUPER_SHOTGUN;
  1139.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1140.         return IT_NAILGUN;
  1141.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1142.         return IT_SHOTGUN;
  1143.         
  1144. /*
  1145.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1146.         return IT_ROCKET_LAUNCHER;
  1147.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1148.         return IT_GRENADE_LAUNCHER;
  1149.  
  1150. */
  1151.  
  1152.     return IT_AXE;
  1153. };
  1154.  
  1155. float() W_CheckNoAmmo =
  1156. {
  1157.     if (self.currentammo > 0)
  1158.         return TRUE;
  1159.  
  1160.     if (self.weapon == IT_AXE)
  1161.         return TRUE;
  1162.     
  1163.     self.weapon = W_BestWeapon ();
  1164.  
  1165.     W_SetCurrentAmmo ();
  1166.     
  1167. // drop the weapon down
  1168.     return FALSE;
  1169. };
  1170.  
  1171. /*
  1172. ============
  1173. W_Attack
  1174.  
  1175. An attack impulse can be triggered now
  1176. ============
  1177. */
  1178. void()  player_axe1;
  1179. void()  player_axeb1;
  1180. void()  player_axec1;
  1181. void()  player_axed1;
  1182. void()  player_shot1;
  1183. void()  player_nail1;
  1184. void()  player_light1;
  1185. void()  player_rocket1;
  1186.  
  1187. void() W_Attack =
  1188. {
  1189.     local   float   r;
  1190.  
  1191.     if (!W_CheckNoAmmo ())
  1192.         return;
  1193.  
  1194.     makevectors     (self.v_angle);                 // calculate forward angle for velocity
  1195.     self.show_hostile = time + 1;   // wake monsters up
  1196.  
  1197.     if (self.weapon == IT_AXE)
  1198.     {
  1199.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1200.         r = random();
  1201.         if (r < 0.25)
  1202.             player_axe1 ();
  1203.         else if (r<0.5)
  1204.             player_axeb1 ();
  1205.         else if (r<0.75)
  1206.             player_axec1 ();
  1207.         else
  1208.             player_axed1 ();
  1209.         self.attack_finished = time + 0.5;
  1210.     }
  1211.     else if (self.weapon == IT_SHOTGUN)
  1212.     {
  1213.         player_shot1 ();
  1214.         W_FireShotgun ();
  1215.         self.attack_finished = time + 0.5;
  1216.     }
  1217.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1218.     {
  1219.         player_shot1 ();
  1220.         W_FireSuperShotgun ();
  1221.         self.attack_finished = time + 0.7;
  1222.     }
  1223.     else if (self.weapon == IT_NAILGUN)
  1224.     {
  1225.         player_nail1 ();
  1226.     }
  1227.     else if (self.weapon == IT_SUPER_NAILGUN)
  1228.     {
  1229.         player_nail1 ();
  1230.     }
  1231.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1232.     {
  1233.         player_rocket1();
  1234.         W_FireGrenade();
  1235.         self.attack_finished = time + 0.6;
  1236.     }
  1237.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1238.     {
  1239.         player_rocket1();
  1240.         W_FireRocket();
  1241.         self.attack_finished = time + 0.8;
  1242.     }
  1243.     else if (self.weapon == IT_LIGHTNING)
  1244.     {
  1245.         player_light1();
  1246.         self.attack_finished = time + 0.1;
  1247.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1248.     }
  1249.     else if (self.weapon == IT_FIREWALL)
  1250.     {
  1251.         W_LaunchBouncer();
  1252.         self.attack_finished = time + 0.4;
  1253.     }
  1254.     else if (self.weapon == IT_BOMB)
  1255.     {
  1256.         W_FireBomb();
  1257.         self.attack_finished = time + 0.8;
  1258.     }    
  1259.     else if (self.weapon == IT_GIBGUN)
  1260.     {
  1261.         W_FireGIBGUN();
  1262.         self.attack_finished = time + 0.4;
  1263.     }    
  1264.     else if (self.weapon == IT_FLASH)
  1265.     {
  1266.         W_FireFLASH();
  1267.         self.attack_finished = time + 1;
  1268.     }    
  1269. };
  1270.  
  1271. /*
  1272. ============
  1273. W_ChangeWeapon
  1274.  
  1275. ============
  1276. */
  1277. void() W_ChangeWeapon =
  1278. {
  1279.     local   float   it, am, fl;
  1280.     
  1281.     it = self.items;
  1282.     am = 0;
  1283.     
  1284.  
  1285.     if (self.impulse == 1)
  1286.     {
  1287.         fl = IT_AXE;
  1288.     }
  1289.     else if (self.impulse == 2)
  1290.     {
  1291.         fl = IT_SHOTGUN;
  1292.         if (self.ammo_shells < 1)
  1293.             am = 1;
  1294.     }
  1295.     else if (self.impulse == 3)
  1296.     {
  1297.         fl = IT_SUPER_SHOTGUN;
  1298.         if (self.ammo_shells < 2)
  1299.             am = 1;
  1300.     }               
  1301.     else if (self.impulse == 4)
  1302.     {
  1303.         fl = IT_NAILGUN;
  1304.         if (self.ammo_nails < 1)
  1305.             am = 1;
  1306.     }
  1307.     else if (self.impulse == 5)
  1308.     {
  1309.         fl = IT_SUPER_NAILGUN;
  1310.         if (self.ammo_nails < 2)
  1311.             am = 1;
  1312.     }
  1313.     else if (self.impulse == 6)
  1314.     {
  1315.         if (self.weapon == IT_GRENADE_LAUNCHER)
  1316.         { 
  1317.             self.weapon = IT_FIREWALL;
  1318.             centerprint(self,"Firewall mode\n");
  1319.             return;
  1320.         } 
  1321.         if (self.weapon == IT_FIREWALL)
  1322.         {
  1323.             self.weapon = IT_BOMB;
  1324.             centerprint(self,"Proximity mine mode\n");
  1325.             return;
  1326.         }  
  1327.  
  1328.         fl = IT_GRENADE_LAUNCHER;
  1329.         if (self.ammo_rockets < 1)
  1330.             am = 1;
  1331.         if (!am) centerprint(self,"Grenade Launcher Mode\n");
  1332.     }
  1333.     else if (self.impulse == 7)
  1334.     {
  1335.         if (self.weapon == IT_ROCKET_LAUNCHER)
  1336.         { 
  1337.             self.weapon = IT_GIBGUN;
  1338.             centerprint(self,"Gibgun mode\n");
  1339.             return;
  1340.         } 
  1341.         if (self.weapon == IT_GIBGUN)
  1342.         { 
  1343.             self.weapon = IT_FLASH;
  1344.             centerprint(self,"Flashgun mode\n");
  1345.             return;
  1346.         } 
  1347.         
  1348.         fl = IT_ROCKET_LAUNCHER;
  1349.         if (self.ammo_rockets < 1)
  1350.             am = 1;
  1351.         if (!am) centerprint(self,"Rocket Launcher Mode\n");
  1352.     }
  1353.     else if (self.impulse == 8)
  1354.     {
  1355.         fl = IT_LIGHTNING;
  1356.         if (self.ammo_cells < 1)
  1357.             am = 1;
  1358.     }
  1359.  
  1360.     self.impulse = 0;
  1361.     
  1362.     if (!(self.items & fl))
  1363.     {       // don't have the weapon or the ammo
  1364.         sprint (self, "no weapon.\n");
  1365.         return;
  1366.     }
  1367.     
  1368.     if (am)
  1369.     {       // don't have the ammo
  1370.         sprint (self, "not enough ammo.\n");
  1371.         return;
  1372.     }
  1373.  
  1374.  
  1375. //
  1376. // set weapon, set ammo
  1377. //
  1378.     self.weapon = fl;               
  1379.     W_SetCurrentAmmo ();
  1380. };
  1381.  
  1382. /*
  1383. ============
  1384. SelfDestruct
  1385. ============
  1386. */
  1387. void() SelfDestruct =
  1388. {
  1389.          if (self.ammo_rockets >= 5)
  1390.          {
  1391.                       if (self.health >= 50)
  1392.                       {
  1393.                                       sprint (self, "Sorry, You Still Got A Little Life In Ya!\n");
  1394.                       }
  1395.                       else
  1396.                       {
  1397.                                       sprint (self, "Have A Nice Day!\n");
  1398.                                       T_RadiusDamage (self, self, 50*self.ammo_rockets, world);
  1399.                                       W_SetCurrentAmmo ();
  1400.                                       sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  1401.  
  1402.                                       WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1403.                                       WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1404.                                       WriteCoord (MSG_BROADCAST, self.origin_x);
  1405.                                       WriteCoord (MSG_BROADCAST, self.origin_y);
  1406.                                       WriteCoord (MSG_BROADCAST, self.origin_z);
  1407.  
  1408.                                       return;
  1409.                       }
  1410.  
  1411.          }
  1412.          else
  1413.          {
  1414.                       sprint (self, "Sorry Mr. Suicide... Not Enough Ammo.\n");
  1415.          }
  1416.         
  1417. };
  1418.  
  1419. /*
  1420. ============
  1421. CheatCommand
  1422. ============
  1423. */
  1424. void() CheatCommand =
  1425. {
  1426.     if (deathmatch || coop)
  1427.         return;
  1428.  
  1429.     self.ammo_rockets = 100;
  1430.     self.ammo_nails = 200;
  1431.     self.ammo_shells = 100;
  1432.     self.items = self.items | 
  1433.         IT_AXE |
  1434.         IT_SHOTGUN |
  1435.         IT_SUPER_SHOTGUN |
  1436.         IT_NAILGUN |
  1437.         IT_SUPER_NAILGUN |
  1438.         IT_GRENADE_LAUNCHER |
  1439.         IT_ROCKET_LAUNCHER |
  1440.         IT_KEY1 | IT_KEY2;
  1441.  
  1442.     self.ammo_cells = 200;
  1443.     self.items = self.items | IT_LIGHTNING;
  1444.  
  1445.     self.weapon = IT_ROCKET_LAUNCHER;
  1446.     self.impulse = 0;
  1447.     W_SetCurrentAmmo ();
  1448. };
  1449.  
  1450. /*
  1451. ============
  1452. CycleWeaponCommand
  1453.  
  1454. Go to the next weapon with ammo
  1455. ============
  1456. */
  1457. void() CycleWeaponCommand =
  1458. {
  1459.     local   float   it, am;
  1460.     
  1461.     it = self.items;
  1462.     self.impulse = 0;
  1463.     
  1464.     while (1)
  1465.     {
  1466.         am = 0;
  1467.  
  1468.         if (self.weapon == IT_LIGHTNING)
  1469.         {
  1470.             self.weapon = IT_AXE;
  1471.         }
  1472.         else if (self.weapon == IT_AXE)
  1473.         {
  1474.             self.weapon = IT_SHOTGUN;
  1475.             if (self.ammo_shells < 1)
  1476.                 am = 1;
  1477.         }
  1478.         else if (self.weapon == IT_SHOTGUN)
  1479.         {
  1480.             self.weapon = IT_SUPER_SHOTGUN;
  1481.             if (self.ammo_shells < 2)
  1482.                 am = 1;
  1483.         }               
  1484.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1485.         {
  1486.             self.weapon = IT_NAILGUN;
  1487.             if (self.ammo_nails < 1)
  1488.                 am = 1;
  1489.         }
  1490.         else if (self.weapon == IT_NAILGUN)
  1491.         {
  1492.             self.weapon = IT_SUPER_NAILGUN;
  1493.             if (self.ammo_nails < 2)
  1494.                 am = 1;
  1495.         }
  1496.         else if (self.weapon == IT_SUPER_NAILGUN)
  1497.         {
  1498.             self.weapon = IT_GRENADE_LAUNCHER;
  1499.             if (self.ammo_rockets < 1)
  1500.                 am = 1;
  1501.         }
  1502.         else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
  1503.         {
  1504.             self.weapon = IT_ROCKET_LAUNCHER;
  1505.             if (self.ammo_rockets < 1)
  1506.                 am = 1;
  1507.         }
  1508.         else if ((self.weapon == IT_ROCKET_LAUNCHER) || (self.weapon == IT_GIBGUN) || (self.weapon == IT_FLASH))
  1509.         {
  1510.             self.weapon = IT_LIGHTNING;
  1511.             if (self.ammo_cells < 1)
  1512.                 am = 1;
  1513.         }
  1514.     
  1515.         if ( (self.items & self.weapon) && am == 0)
  1516.         {
  1517.             W_SetCurrentAmmo ();
  1518.             return;
  1519.         }
  1520.     }
  1521.  
  1522. };
  1523.  
  1524. /*
  1525. ============
  1526. ServerflagsCommand
  1527.  
  1528. Just for development
  1529. ============
  1530. */
  1531. void() ServerflagsCommand =
  1532. {
  1533.     serverflags = serverflags * 2 + 1;
  1534. };
  1535.  
  1536. void() QuadCheat =
  1537. {
  1538.     if (deathmatch || coop)
  1539.         return;
  1540.     self.super_time = 1;
  1541.     self.super_damage_finished = time + 30;
  1542.     self.items = self.items | IT_QUAD;
  1543.     dprint ("quad cheat\n");
  1544. };
  1545.  
  1546. /*
  1547. ============
  1548. ImpulseCommands
  1549.  
  1550. ============
  1551. */
  1552. void() ImpulseCommands =
  1553. {
  1554.     if (self.impulse >= 1 && self.impulse <= 8)
  1555.         W_ChangeWeapon ();
  1556.  
  1557.     if (self.impulse == 9)
  1558.         CheatCommand ();
  1559.     if (self.impulse == 10)
  1560.         CycleWeaponCommand ();
  1561.     if (self.impulse == 11)
  1562.         ServerflagsCommand ();
  1563.     
  1564.     // PATCH FOR BOUNCERS
  1565.  
  1566.     if (self.impulse == 20)
  1567.         {
  1568.         W_LaunchBouncer ();
  1569.         self.attack_finished = time + 0.4;
  1570.         }
  1571.  
  1572.     if (self.impulse == 69)
  1573.                 SelfDestruct ();    
  1574.  
  1575.     if (self.impulse == 21)
  1576.         {
  1577.         W_FireBomb ();
  1578.         self.attack_finished = time + 0.8;
  1579.         }
  1580.     if (self.impulse == 22)
  1581.         {
  1582.         W_FireGIBGUN ();
  1583.         self.attack_finished = time + 0.4;
  1584.         }
  1585.     if (self.impulse == 23)
  1586.         {
  1587.         W_FireFLASH ();
  1588.         self.attack_finished = time + 1;
  1589.         }
  1590.  
  1591.     if (self.impulse == 255)
  1592.         QuadCheat ();
  1593.         
  1594.     self.impulse = 0;
  1595. };
  1596.  
  1597. /*
  1598. ============
  1599. W_WeaponFrame
  1600.  
  1601. Called every frame so impulse events can be handled as well as possible
  1602. ============
  1603. */
  1604. void() W_WeaponFrame =
  1605. {
  1606.     if (time < self.attack_finished)
  1607.         return;
  1608.  
  1609.     ImpulseCommands ();
  1610.     
  1611. // check for attack
  1612.     if (self.button0)
  1613.     {
  1614.         SuperDamageSound ();
  1615.         W_Attack ();
  1616.     }
  1617. };
  1618.  
  1619. /*
  1620. ========
  1621. SuperDamageSound
  1622.  
  1623. Plays sound if needed
  1624. ========
  1625. */
  1626. void() SuperDamageSound =
  1627. {
  1628.     if (self.super_damage_finished > time)
  1629.     {
  1630.         if (self.super_sound < time)
  1631.         {
  1632.             self.super_sound = time + 1;
  1633.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1634.         }
  1635.     }
  1636.     return;
  1637. };
  1638.  
  1639.  
  1640. /***********************************************************************************
  1641. ================
  1642. W_FireBomb
  1643. ================
  1644. ************************************************************************************/
  1645. void() W_FireBomb =
  1646. {
  1647.     local   entity missile, mpuff;
  1648.  
  1649.     if ((self.ammo_rockets < 5) || !(self.weapon & (IT_GRENADE_LAUNCHER | IT_FIREWALL | IT_BOMB )))
  1650.     {
  1651.         return;
  1652.     }
  1653.  
  1654.  
  1655.     if (bombtimer >0 )
  1656.     {
  1657.         return;
  1658.     }
  1659.     else     bombtimer=1.5;
  1660.  
  1661.  
  1662.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  1663.     
  1664.  
  1665.  
  1666.     self.punchangle_x = -10;
  1667.  
  1668.     missile = spawn ();
  1669.     missile.owner = self;
  1670.     missile.movetype = MOVETYPE_FLY;
  1671.     missile.solid = SOLID_TRIGGER;
  1672.     missile.classname = "Bomb";
  1673.         
  1674. // set missile speed    
  1675.  
  1676.     makevectors (self.v_angle);
  1677.  
  1678.  
  1679.     missile.velocity= '0 0 0';
  1680.     missile.avelocity= '0 0 0';
  1681.     
  1682.     missile.touch = BombTouch;
  1683.     
  1684. // set missile duration
  1685.     missile.nextthink = time + 0.25;
  1686.     missile.think = BombTime;
  1687.  
  1688.     setmodel (missile, "progs/grenade.mdl");
  1689.     setsize (missile, '-48 -48 -4', '48 48 4');            
  1690.     setorigin (missile, self.origin - '0 0 20');
  1691. //    sprint(self,"Better stay the hell clear now\n");
  1692. };
  1693.  
  1694. void() BombTime =
  1695. {
  1696.     bombtimer = bombtimer - 0.25;
  1697.     if (bombtimer)
  1698.         {
  1699.         if (bombtimer == 0.5) self.velocity='0 0 24';
  1700.         sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  1701.         self.nextthink = time + 0.25;
  1702.         self.think = BombTime;
  1703.         } 
  1704.     else
  1705.     {
  1706.         self.nextthink = time + 180;
  1707.         self.think = BecomeExplosion;
  1708.         self.classname = "ArmedBomb";
  1709.         self.velocity='0 0 0';
  1710.         self.avelocity='0 800 800';
  1711.         
  1712.         self.health = 20;
  1713.         self.th_die = BombExplode;
  1714.         self.takedamage = DAMAGE_AIM;
  1715.  
  1716.     }
  1717. };
  1718.  
  1719. void() BombTouch =
  1720. {
  1721.     if (other.takedamage && (self.classname == "ArmedBomb") && (other.classname != "ArmedBomb"))
  1722.     {
  1723.         BombExplode();
  1724.         return;
  1725.     }
  1726.  
  1727. };
  1728.  
  1729. void() BombExplode =
  1730. {
  1731.     T_RadiusDamage (self, self.owner, 120, world);
  1732.  
  1733.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1734.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1735.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1736.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1737.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1738.  
  1739.     BombExplosion ();
  1740. };
  1741.  
  1742. void() BombExplosion =
  1743. {
  1744.     sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
  1745.     self.movetype = MOVETYPE_NONE;
  1746.     self.velocity = '0 0 0';
  1747.     self.touch = SUB_Null;
  1748.     setmodel (self, "progs/s_explod.spr");
  1749.     self.solid = SOLID_NOT;
  1750.     s_explode1 ();
  1751. };
  1752.  
  1753. void() ShrapnelExplode =
  1754. {
  1755.     T_RadiusDamage (self, self.owner, 120, world);
  1756.  
  1757.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1758.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1759.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1760.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1761.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1762.  
  1763.     BecomeExplosion ();
  1764. };
  1765.  
  1766. void() GIBExplode =
  1767. {
  1768.     local entity loser;
  1769.     self.wait = self.wait - 1;
  1770.     loser = self.trigger_field;
  1771.  
  1772.     if ((self.wait == 30) || (self.wait == 20) || (self.wait == 10))     sound (self, CHAN_WEAPON, "player/tornoff2.wav", 1, ATTN_NORM);    
  1773.     if (((self.wait == 35) || (self.wait == 25) || (self.wait == 15)) && (loser.classname == "player"))     sound (self, CHAN_WEAPON, "player/lburn1.wav", 1, ATTN_NORM);    
  1774.  
  1775.     if ((!self.wait) || (loser.health<=10))
  1776.     {
  1777.     T_RadiusDamage (self, self.owner, 120, world);
  1778.  
  1779.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1780.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1781.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1782.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1783.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1784.  
  1785.     BecomeExplosion ();
  1786.     return;
  1787.     }
  1788.  
  1789.     
  1790.     T_Damage (loser, self, self.owner, 2.5 );
  1791.     spawn_touchblood (30);
  1792.  
  1793.     self.origin = loser.origin + '0 0 12';
  1794.     self.nextthink = time + 0.05;
  1795.     self.think = GIBExplode;
  1796.         
  1797. };
  1798.  
  1799. void() T_GIBTouch =
  1800. {
  1801.     local float     damg;
  1802.  
  1803.     if (other == self.owner)
  1804.         return;         // don't explode on owner
  1805.  
  1806.     if (pointcontents(self.origin) == CONTENT_SKY)
  1807.     {
  1808.         remove(self);
  1809.         return;
  1810.     }
  1811.  
  1812.  
  1813.     
  1814.     if (other.takedamage)
  1815.     {
  1816.         sound (self, CHAN_WEAPON, "player/tornoff2.wav", 1, ATTN_NORM);    
  1817.         self.trigger_field = other;
  1818.         self.origin = other.origin + '0 0 12';
  1819.         self.wait = 40;
  1820.  
  1821.         self.nextthink = time + 0.05;
  1822.         self.think = GIBExplode;
  1823.         self.movetype = MOVETYPE_NOCLIP;
  1824.         self.velocity = '0 0 0' ;
  1825.         self.avelocity = '0 0 1000';
  1826.         return;
  1827.     }
  1828.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  1829. //    remove(self);
  1830.     self.nextthink = time + 0.3;
  1831.     self.think = SUB_Remove;
  1832.     self.movetype = MOVETYPE_NOCLIP;
  1833.     self.velocity = ' 0 0 0';
  1834.     self.avelocity = '0 0 1000';
  1835. };
  1836.  
  1837.  
  1838.  
  1839. /*
  1840. ================
  1841. W_FireGIBGUN
  1842. ================
  1843. */
  1844. void() W_FireGIBGUN =
  1845. {
  1846.     if ((self.ammo_rockets < 1) || !(self.weapon & (IT_ROCKET_LAUNCHER | IT_GIBGUN | IT_FLASH)))
  1847.     {
  1848.         return;
  1849.     }
  1850.     local   entity missile, mpuff;
  1851.     
  1852.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  1853.     
  1854.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  1855.  
  1856.     self.punchangle_x = -2;
  1857.  
  1858.     missile = spawn ();
  1859.     missile.owner = self;
  1860.     missile.movetype = MOVETYPE_FLYMISSILE;
  1861.     missile.solid = SOLID_BBOX;
  1862.     missile.classname = "GibGun";
  1863.     
  1864. // set missile speed    
  1865.  
  1866.     makevectors (self.v_angle);
  1867.     missile.velocity = aim(self, 1000);
  1868.     missile.velocity = missile.velocity * 1000;
  1869.     missile.angles = vectoangles(missile.velocity);
  1870.     
  1871.     missile.touch = T_GIBTouch;
  1872.     
  1873. // set missile duration
  1874.     missile.nextthink = time + 5;
  1875.     missile.think = SUB_Remove;
  1876.     setmodel (missile, "progs/missile.mdl");
  1877.     setsize (missile, '0 0 0', '0 0 0');            
  1878.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  1879. };
  1880.  
  1881. /*
  1882. ================
  1883. W_FireFlash
  1884. ================
  1885. */
  1886. void() W_FireFLASH =
  1887. {
  1888.     if ((self.ammo_rockets < 5) || !(self.weapon & (IT_ROCKET_LAUNCHER | IT_GIBGUN | IT_FLASH)))
  1889.     {
  1890.         return;
  1891.     }
  1892.     local   entity missile, mpuff;
  1893.     
  1894.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  1895.     
  1896.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  1897.  
  1898.     self.punchangle_x = -2;
  1899.  
  1900.     missile = spawn ();
  1901.     missile.owner = self;
  1902.     missile.movetype = MOVETYPE_FLYMISSILE;
  1903.     missile.solid = SOLID_BBOX;
  1904.     missile.classname = "Flash";
  1905.     
  1906. // set missile speed    
  1907.  
  1908.     makevectors (self.v_angle);
  1909.     missile.velocity = aim(self, 100000);
  1910.     missile.velocity = missile.velocity * 800;
  1911.     missile.angles = vectoangles(missile.velocity);
  1912.     
  1913.     missile.touch = T_FlashTouch;
  1914.     
  1915. // set missile duration
  1916.     missile.nextthink = time + 5;
  1917.     missile.think = SUB_Remove;
  1918.  
  1919.     setmodel (missile, "progs/missile.mdl");
  1920.     setsize (missile, '0 0 0', '0 0 0');            
  1921.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  1922.  
  1923. };
  1924.  
  1925. void() T_FlashTouch =
  1926. {
  1927.     local float     damg;
  1928.  
  1929.     if (other == self.owner)
  1930.         return;         // don't explode on owner
  1931.  
  1932.     if (pointcontents(self.origin) == CONTENT_SKY)
  1933.     {
  1934.         remove(self);
  1935.         return;
  1936.     }
  1937.     
  1938.     self.effects = self.effects | EF_BRIGHTLIGHT;        
  1939.     damg = 20;
  1940.     
  1941.     if (other.health)
  1942.     {
  1943.         if (other.classname == "monster_shambler")
  1944.             damg = damg * 0.5;      // mostly immune
  1945.         T_Damage (other, self, self.owner, damg );
  1946.     }
  1947.  
  1948.     // don't do radius damage to the other, because all the damage
  1949.     // was done in the impact
  1950.     T_RadiusDamage (self, self.owner, 20, other);
  1951.     T_FlashDamage (self, self.owner,1000, self);
  1952.  
  1953.         sound (self, CHAN_WEAPON, "doors/airdoor2.wav", 1, ATTN_NORM);
  1954.     self.origin = self.origin - 8*normalize(self.velocity);
  1955.     
  1956.  
  1957.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1958.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1959.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1960.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1961.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1962.  
  1963.     BecomeExplosion ();
  1964. };